Singleton Pattern 1-23
Published Date: 2020-04-03 21:32:12Z
In some cases we will need a "settings" to transmit args, this "settings" suppose to be:
- Containing many types, a class would be fine.
- Can get it anywhere, better not using arguments.
- Thread-Safe.
By the first and the second conditions, we can easily figure out a prototype like-
class Settings:
def __init__(self):
self.aBool = True
self.aInt = 32
self.aChar = 'a'
self.aString = "HelloWorld"
self.aIntArray = [0,3,4,1,4]
self.aStringIntDict = {"Hello": 5, "World!": 6}
......
settings = Settings()
We can use it anywhere, eg.:
def aFun(x: str) -> str:
return x + settings.aString
def anotherFun(y: int) -> int:
return y + settings.aInt
But this is a global var and may cause problem by mistakes, eg.:
......
settings = aSettingFromAnotherFile()
settings.set(x=x,y=y)
......
In this stage, the "settings" is no longer the "settings" we said before, if we need the "settings" instance unique and always be there, I believe singleton would be the best choice.
def singleton(fun):
ins = {}
def getSingleton(*args,**kw):
if fun not in ins:
ins[fun] = fun(*args,**kw)
return ins[fun]
return getSingleton
@singleton
class Settings:
def __init__(self):
self.aBool = True
self.aInt = 32
self.aChar = 'a'
self.aString = "HelloWorld"
......
settings = Settings()
settings.aBool = False
settings.aInt = 64
print(settings.aBool, settings.aInt)
# Output:
# False 64
otherSettings = Settings()
print(settings is otherSettings)
# Output:
# True
If your code runs fine in single thread, then I guess it's safe in multithreads too (unless you create the instance in threads).
Extra:
If you create the "settings" in threads then multiple instances might be created, we can use thread lock to solve the problem.
import threading
def singleton(Fun):
ins = {}
def getSingleton( *args, **kw):
if Fun not in ins:
getSingleton.__lock__ = threading.Lock()
with getSingleton.__lock__:
if Fun not in ins:
ins[Fun] = Fun( *args, **kw)
return ins[Fun]
return getSingleton
@singleton
class Settings:
def __init__(self):
self.aBool = True
self.aInt = 32
self.aChar = 'a'
self.aString = "HelloWorld"
......
settings = Settings()